\ Lesson 3. Numbers
comment:
In this lesson we shall discuss the way Forth handles
integers.
Integers are numbers from -32768 to 32767. This range of number
is most convenient to be stored and proceesed in
Forth. It is
very surprising that many real world problems can be
represented
and solved using numbers in this range. Forth can handle larger
numbers and even floating point numbers, but these
are topics
outisde of the scope of this lesson.
Example 1.
Money Exchange
The first example we will use to demonstrate how
numbers are
used in Forth is a money exchange program, which
converts money
represented in different currencies. Let's start with the
following currency exchange table:
24.55 NT 1
Dollar
7.73
HK
1 Dollar
5.47
RMB
1 Dollar
1
Ounce Gold 356 Dollars
1
Ounce Silver 4.01 Dollars
We shall use the US dollar as the standard currency
and convert
all other currencies to dollar first. All arithmatic operations
then will be carried out in dollars. From dollars, the money can
then be converted back to any other currency.
We define words converting other currencies to the
dollar using
the names of the corresponding currencies. To convert dollars
to a currency, the words is preceeded by the '$'
sign.
comment;
: NT
( nNT -- $ ) 10
245 */ ;
: $NT
( $ -- nNT ) 245
10 */ ;
: RMB
( nRMB -- $ ) 100 547
*/ ;
: $jmp (
$ -- nJmp ) 547 100 */ ;
: HK
( nHK -- $ ) 100
773 */ ;
: $HK
( $ -- $ )
773 100 */ ;
: gold (
nOunce -- $ ) 356 * ;
: $gold ( $ -- nOunce ) 356 / ;
: silver ( nOunce -- $ ) 401 100 */ ;
: $silver ( $ -- nOunce ) 100 401 */ ;
: ounce ( n -- n, a word to improve syntax ) ;
: dollars ( n -- ) . ;
comment:
With this set of money exchange words, we can do some
tests:
5
ounce gold .
10
ounce silver .
100
$NT .
20
$RMB .
If you have many different currency bills in your
wallet, you
can add then all up in dollars:
1000
NT 500 HK + .s
320
RMB + .s
dollars ( print out total worth in dollars )
'DOLLARS' is idenitcal to '.', which simply displays
a number.
Use 'DOLLARS' to display the total amount of money is
natural
in the syntax of English.
If I am in Hong Kong at the time, the total amount
can be
readily converted to Hong Kong dollars:
1000
NT 500 HK + 320 RMB + .s
$HK
dollars ( convert total to Hong Kong dollar and print it)
Exercise 1.
A Business Trip
Now we have a fairly powerful money exchange computer
with us.
Suppose you depart San Francisco with 1000 dollars in
your pocket.
You go to Hong Kong and buy a VCR with 1200 HK. Go to
Shanghai and
sell it for 2000 RMB. Then you come back to Hong Kong and
spent
900 HK for fun.
Go to Taipei and buy a portable PC with 30000 NT.
How much money in US dollar do you have remaining?
The answer typed backwards is:
srallod - TN 00003 - KH 009 + BMR 0002 - KH 0021 0001
Try it.
Example 2. Temperature Conversion
Converting temperature readings between Celcius and
Farenheit
is also an interesting problem. The difference between temperature
conversion and money exchange is that the two
temperature scales
have an offset besides the scaling factor.
comment;
: F>C ( nFarenheit -- nCelcius )
32 -
10
18 */
;
: C>F ( nCelcius -- nFarenheit )
18
10 */
32 +
;
comment:
90 F>C .
shows the temperature in a hot summer day and
0 C>F .
shows the temperature in a cold winter night.
In the above examples, we use the following Forth
arithmatic
operators:
+ ( n1 n2 --
n1+n2 ) Add
n1 and n2 and leave sum on stack.
- ( n1 n2 --
n1-n2 )
Subtract n2 from n1 and leave differrence
on stack.
* ( n1 n2 --
n1*n2 )
Multiply n1 and n2 and leave product
on stack.
/ ( n1 n2 --
n1/n2 )
Divide n1 by n2 and leave quotient on
stack.
*/ ( n1 n2 n3 --
n1*n2/n3) Multiply n1 and n2, divide the product
by n3 and leave quotient on the stack.
.s ( ... -- ...
)
Show the topmost 4 numbers on stack.
Here we have to introduce the concept of a
stack. A stack is a memory
area in the computer where numbers are stored and
retrieved
implicitly.
It is different from variables discussed in Lesson 1.
Variables are named locations in memory, which are
accessed by
referring to the assigned names. Stack is a First-In-Last-out (FIFO)
list.
When a number is given to Forth, it is pushed on the stack.
Any operator which uses numbers pops the required
numbers from the
stack. The
most accessible number is on the top of the stack, like
the card on the top of a card deck. Various Forth instructions may
produce one or many numbers and the numbers are
pushed on the stack
as they are generated.
+ thus pops the two topmost numbers off the stack,
adds them together,
and then pushes the sum back on the stack. -, *, and / are the
commonly used operators to do simple math. One must notice that
the order of the two numbers used by + and * is
immaterial, while the
order is important for - and /. Exchanging the two numbers will produce
different difference or quotient, respectively.
*/ is a scaling operator in Forth, which is most
useful in scaling
integer numbers.
It multiplies n1 by the ratio of (n2/n3). As shown
in Examples 1 and 2, this operator is very useful in
scaling
quantities from one unit to another. Scaling is a very powerful
operation which eliminates the necessity of using
floating point
numbers.
.s is a powerful debugging tool which shows you the
contents of the
topmost 4 items on the stack. It is used often during debugging
to make sure that the stack has the correct numbers
for your
calculations.
It is generally not used in the final program to
avoid printing too many intermediate values.
Several other less commonly used, but important math
operators are:
MOD ( n1 n2 -- rem )
Divide n1 by n2 and leave the remainder
on stack.
/MOD
( n1 n2 -- rem quot )
Divide n1 by n2 and leave both remainder
and quotient on stack.
ABS ( n -- |n| )
Convert top number on stack to absolute.
NEGATE (
n -- -n )
Negate n on stack.
As we go along, some of these operators will be used
as occassions
arise.
Stack Operators
Stack is the most important place where the results
of previously
executed operators can be passed to the operators yet
to be executed.
Operators taking their parameters from the stack and
leaving their
results on the stack for subsequent operator to use
can be built
easily from stringing subroutines together. The subroutines can call
other subroutines, and so forth. The subroutines are Forth operators,
and they can be nested almost indefinitely. This is a very important
reason why Forth is simple in its architecture and
also in its
syntactical strucuture.
However, it happens very often that the odering of
numbers on the
stack is not correct for a operator which needs them,
like - and /.
There is a set of stack operators which rearranges
numbers on the
stack.
The five most important classic stack operators are:
DUP ( n -- n n )
Duplicate the top of stack.
SWAP
( n1 n2 -- n2 n1 ) Exchange to top
two numbers on stack.
OVER
( n1 n2 -- n1 n2 n1 )
Duplicate the second number on stack.
ROT ( n1 n2 n3 -- n2 n3
n1) Rotate 3rd number to the top of stack.
DROP
( n -- )
Discard the top of stack.
Example 3.
Rectangles
A rectangle is specified by the (x,y) coordinates of
its upper-left
and lower-right corners. With these four integers on the stack,
we can compute the area, the center, and the
perimenter of a
rectangle:
: area ( x1 y1 x2 y2 -- area )
ROT
- ( x1 x2 y2-y1 )
SWAP
ROT - ( y2-y1 x2-x1 )
* (
area )
;
: center ( x1 y1 x2 y2 -- x3 y3 , center coordinates
)
ROT
- 2/ ( x1 x2 y3 )
SWAP
ROT - 2/ ( y3 x3 )
SWAP
( x3 y3 )
;
: sides ( x1 y1 x2 y2 -- sides )
ROT
- ABS ( x1 x2 y2-y1 )
SWAP
ROT - ABS ( y2-y1 x2-x1 )
+ (
sides )
;
Logic Operators
Computer uses logic operators to determine and follow
different execution
paths.
Logic operators themselves are very simple and easy to
understand.
However, the combination of many levels of logic
operations and the multitude of different pathways in
a large
program make the computer seem very complicated, even
to the point
of showing some intelligence.
Here we introduce some of the logic operators
associated with
numbers, and the branching operators which use the
results of
logic operators to select different operations.
Forth uses numbers to represent logic levels. There are only two
logic levels, true and false. True is represented by any number
which is not zero, and false is represented by
zero. Which a Forth
logic operator returns a true level, it usually
returns a -1. The
number representing logic levels is also called a
flag.
> ( n1 n2 --
f )
Return true if n1>n2.
Otherwise
return false.
< ( n1 n2 --
f )
Return true if n1<n2.
= ( n1 n2 --
f )
Return true if n1=n2.
0= ( n -- f )
Return true if n=0.
0< ( n -- f ) Return
true if n<0.
NOT ( f1 -- f2 )
Return true if f1 is false.
Return
false if f1 is true.
AND ( n1 n2 -- n3 )
n3 is bitwise AND of n1 and n2.
OR ( n1 n2 -- n3
)
N3 is bitwise OR of n1 and n2.
Note that AND and OR will operate correctly on true
and false flags.
true
true AND -- true
true
false AND -- false
false false AND -- false
true
true OR -- true
true
false OR -- true
false false OR -- flase
A flag can be used to select one of the two execution
paths by
the following constructs inside a colon definition:
( f
) IF <true clause> ELSE <false clause> THEN
( f
) IF <true clause> THEN
They were briefly discussed in Lesson 2. Now that we know how to
generate flags, you will appreciate them better in
conjunction with
the logic instructions.
Example 4.
Weather Reporting.
The following colon definition illustrates the use of
logic and
the branch:
comment;
: weather ( nFarenheit -- )
DUP 85
>
IF
." Too hot!" DROP
ELSE 55 <
IF
." Too cold."
ELSE ."
About right."
THEN
THEN
;
comment:
You can type the following instructions and get some
responses from the
computer:
90
weather Too hot!
70
weatehr About right.
32
weather Too cold.
Review of Loop instructions
We shall be concerned now with only the definite loop
instructions
used in the following format in a colon definition:
(
nLimit nIndex ) DO <repeat clause> LOOP
DO takes two parameters off the stack. The top number is the
starting index of the loop and the second number is
the upper
limit of the loop index. After entering the loop,
the <repeat clause> is repeatedly
executed. LOOP increments the
loop index from nIndex to nLimit. When the index is equal to
nLimit, the loop is terminated. In the <repeat clause> a special
operator I returns the current loop index on the
stack.
A simple example of the loop structure is as follows:
Example 5.
Print the multiplication table
comment;
: OneRow ( nRow -- )
CR
DUP
3 .R 3 SPACES
13 1
DO I
OVER *
4 .R
LOOP
DROP
;
: Table ( -- )
CR
CR 6 SPACES
13 1
DO I
4 .R LOOP ( display column numbers )
13 1
DO I
OneRow
LOOP
;
comment:
Typing TABLE will cause the multiplication table to
be displayed
in a very neat format.
Exercise 1. In US, the
multiplation table ends at 12*12.
In
China and most metric countries, the multiplication
table usually
ends at 9*9.
Modify the definition of TABLE so that the table
is limited from 1*1 to 9*9.
With all these new Forth operator introduced, we can
now write
a fairly substantial program using many of the operators
to
demonstrate how they are combined to do some useful
work.
comment;